综述
ActivityManagerService 即活动管理服务,它负责管理我们应用的activity,service等与系统交互的组件,为了方便起见,我们简称为AMS。我们知道Activity在启动过程中会经历一系列的生命周期,这些生命周期反应了AMS创建和管理Activity的整个过程,并且在这之间又同时需要和WindowManagerService进行交互操作,这就导致activity的启动是个异常复杂的工作。本篇不打算对整个流程的细节做过多的分析,只涉及activity启动过程的关键部分。
Activity启动方式-Launcher
首先activity的启动方式有多种可能的情况,比如最典型的就是点击Launcher上的图标启动,或者在应用内部打开activity进行跳转,还有通过adb 来启动activity,但无论是哪种启动方式,最基本的流程都是类似的。这里我们以Launcher启动作为描述的标准场景来简单了解下在activity启动过程中都会发生什么事情以使activity能够展现在我们眼前。
Launcher是一个标准的系统桌面应用,它用来管理系统中的所有已安装的app,这些app都是以网格化的形式在Launcher中显示的。我们点击一个app图标就会开始启动整个app并启动它的主activity。
Launcher启动是会给Intent添加flag Intent.FLAG_ACTIVITY_NEW_TASK,这表示我们会为这个应用创建一个新的任务栈。紧接就是启动指定的activity,正式开始startActivity的启动。
1 | packages/apps/Launcher2/src/com/android/launcher2/Launcher.java |
从Launcher启动的activity默认添加了FLAG_ACTIVITY_NEW_TASK,表示为应用创建新的任务栈。
这里我们从Launcher启动传递给startActivityForResult的requestCode为-1,说明我们不接受activity的返回值。
1 | Activity: startActivity->startActivityForResult |
execStartActivity 参数说明,对于Launcher启动:
- who: 为Launcher应用
- mMainThread.getApplicationThread(): 为Launcher的ApplicationThread它是一个Binder
- target: 为this 代表Launcher这个Activity
- requestCode: -1
- intent: 为要启动应用的Activity的意图
- options: null
这里通过Instrumention来调用execStartActivity
1 | 2.[Instrumention.execStartActivity]===>[AMS.startActivity] |
在Instrumention中会通过ActivityManagerNative获取到AMS的代理,到这里就开始通过Binder进行IPC调用了。我们这里继续看AMS中startActivity的实现,AMS时SystemServer进程中的众多服务之一,关于它启动的细节请参见SystemServer.java.
1 | [AMS.startActivity]===>[AMS.startActivityAsUser] |
这里我们对传递的参数做个说明:
- caller:代表Launcher的ApplicationThread 它是个Binder对象
- callingPackage: 调用者即Launcher的包名
- Intent: 要启动的activity的意图
- resolvedType: Intent中指定的MIME类型 一般不指定的为null
- resultTo : token 代表着Launcher的activityRecord的- appToken,实际上就是代表着Launcher.
- resultWho : null
- requestCode:-1
- startFlags : 0
- profileFile:-1
- profileFd:null
- Options:null
1 |
|
AMS作为activity的管理者,它很懒,不做什么事情,几乎大部分Service都类似,他们不会真正的做事情,而是交给其他的"代理"对象去做事情。这里的"代理"对象就是ActivityStackSupervisor从名称上来看它负责监控和管理ActivityStack。
1 | frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java |
startActivityMayWait方法中会从待启动的activity的intent中获取ActivityInfo,随后再去设置callingPid 和 callingUid为-1.在进一步调用startActivityLocked。
1 | frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java |
这个方法主要做的事情包括:
1.初始化调用者的进程id和用户id,这是通过查找它的ProcessRecord来进行的。
2.做一些权限检查,比如调用者的权限和启动组件的权限等
3.为待启动的activity创建AtivityRecord,同时会创建appToken,用来代表这个ActivityRecord,间接代表要启动的activity.
4.进一步调用startActivityUncheckedLocked来进一步启动,这里的sourceRecord为Launcher的ActivityRecord。r就是我们要启动的activity的activityRecord
1 | final int startActivityUncheckedLocked(ActivityRecord r, |
这一步会首先为要启动的activity找到一个task,然而由Launcher启动的时候activity的task还并未创建,这时候需要为其创建一个task并通过setTask设置到r中去。紧接着这里调用startActivityLocked进一步处理,同时将mLastPausedActivity置null,表示当前没有被暂停的activity。将mFocusedActivity设置为当前的activity,表示为焦点activity.对于Launcher启动这里newTask为true。
1 | final void startActivityLocked(ActivityRecord r, boolean newTask, |
这一步首先将要启动的activity对应的ActivityRecord 即r放到其对应TaskRecord的顶部,然后将其Task设置为前台栈.随后为该Activity添加AppWindowToken,这个token时WMS用来标记AMS端的Activity对应的window的。最后调用resumeTopActivitiesLocked进一步处理栈顶activity.
1 | boolean resumeTopActivitiesLocked() { |
1 | final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { |
这组方法用来恢复启动task栈顶的activity,其中next即我们要执行的activity,它已经被放在了task栈顶,这里如果next已经在相关的休眠或者停止队列中需要将其从中移除,并重置sleeping状态,这些都是为next的启动做准备。这里最重要的一步就是需要将当前正在执行的mResumedActivity 暂停,这样才能执行task栈顶的activity .这是通过startSpercificActivityLocked来执行的。
1 | void startSpecificActivityLocked(ActivityRecord r, |
这个方法用来启动我们具体的activity,首先获取activity对应的进程信息ProcessRecord,由于Launcher启动,activity的进程还未创建,所以这里需要为activity创建进程。
1 | private final void startProcessLocked(ProcessRecord app, |
到这里会通过zygote为activity创建进程,这是通过和zygote进程通过socket通信来完成的,zygote为Activity创建进程后,会调用ActivityThread的main方法。
我们看看ActivityThread的main方法
1 | public static void main(String[] args) { |
进程启动后需要创建要给ActivityThread对象,并调用其attach方法。在attach方法中会做许多初始工作。从main方法可以看到进程的主线程是作为ui线程的。
1 | private void attach(boolean system) { |
在attach方法中会调用AMS的attachApplicaton,这里的mAppThread是我们的ApplicationThread对象,它是一个binder服务,在ActivityThread对象创建的时候生成,它在这里传递给AMS,这样AMS就可以使用其代理binder来和应用程序进行通信。比如activity众多的生命周期事件是通过这个binder对象通知应用端的。
1 |
|
1 | private final boolean attachApplicationLocked(IApplicationThread thread, |
这里AMS做一些初始化工作后 又会调用到应用端的bindApplication。应用端会在这个时机为应用创建Application对象,随后AMS分别调用mStackSupervisor和mServices的attachApplicationLocked,这里会将等待启动的acitivty或者service启动起来。后面我们继续分析
1 | public final void bindApplication(String processName, |
这里会通过H对象 其实是个handler 来发送BIND_APPLICATION消息,这会调用handleBindApplication方法来处理该消息。
1 | private void handleBindApplication(AppBindData data) { |
在应用端的handleBindApplication时会为应用创建application对象,同时调用onCreate回调。
1 | boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception { |
AMS回调完成应用端的application初始化后,会进一步调用attachApplicationLocked来继续执行activity的任务。在这个方法中首先取到前台的ActivityStack,然后找到task栈顶的activity,最后通过realStartActivityLocked来真正的启动hr所代表的activity.
1 | frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java |
到这一步,WMS会将app的设置为可见,这里是将r.appToken作为key的,这个appToken是我们在为activity创建ActivityRecord时创建的,它作为一个Binder用来在WMS端标记我们的activity,同时也可以和WMS通信。随后通知应用端开始加载Activity,App.thread就是我们的ApplicationThread,它是在进程创建后,应用端的binder server,主要被AMS使用和应用端的通信。
1 | public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, |
在scheduleLaunchActivity中构造了一个 ActivityClientRecord对象,随后发送H_LAUNCH_ACTIVITY,然后调用handleLaunchActivity。
1 | private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { |
到这里就开始加载activity,首先是调用performLaunchActivity,这里面会去调用onCreate和onStart等回调,而handleResumeActivity中会将activity显示出来,并调用onResume回调。
1 | private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { |
这个方法主要创建activity对象,并为其创建context,实际上为contextImpl,通过attach方法将context设置到activity中。同时为activity设置window,即PhoneWindow.
随后回调onCreate,onStart等方法。
1 | final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, |
到这里就真正的将activity相应的window添加到了WMS中,activity被显示在桌面上。